/****************************************************************************************************************************
  ESP8266-RepeatingClient.ino
  For ESP8266.
  
  Based on and modified from Gil Maimon's ArduinoWebsockets library https://github.com/gilmaimon/ArduinoWebsockets
  to support STM32F/L/H/G/WB/MP1, nRF52 and SAMD21/SAMD51 boards besides ESP8266 and ESP32


  The library provides simple and easy interface for websockets (Client and Server).
  
  Built by Khoi Hoang https://github.com/khoih-prog/Websockets2_Generic
  Licensed under MIT license
 *****************************************************************************************************************************/
/****************************************************************************************************************************
  ESP8266 Websockets Repeating Client

  This sketch:
        1. Connects to a WiFi network
        2. Connects to a Websockets server
        3. Sends the websockets server a message ("Hello to Server from ......")
        4. Prints all incoming messages while the connection is open
        5. Repeat 2-4 every REPEAT_INTERVAL (10 seconds)

  Hardware:
        For this sketch you only need an ESP8266 board.

  Originally Created  : 15/02/2019
  Original Author     : By Gil Maimon
  Original Repository : https://github.com/gilmaimon/ArduinoWebsockets

*****************************************************************************************************************************/

#include "defines.h"
#include <Adafruit_NeoPixel.h>
#include <WebSockets2_Generic.h>
#include <ESP8266WiFi.h>

using namespace websockets2_generic;
int pin =0;
int var =0;
WebsocketsClient client;
int status=0;//连接状态,初始为 0 代表关闭
void onEventsCallback(WebsocketsEvent event, String data) 
{
  if (event == WebsocketsEvent::ConnectionOpened) 
  {
    Serial.println("Connnection Opened");
  } 
  else if (event == WebsocketsEvent::ConnectionClosed) 
  {
    Serial.println("Connnection Closed");
    status=0;//当和服务器关闭连接后设置为关闭状态
  } 
  else if (event == WebsocketsEvent::GotPing) 
  {
    Serial.println("Got a Ping!");
  } 
  else if (event == WebsocketsEvent::GotPong) 
  {
    Serial.println("Got a Pong!");
  }
}





void setup() 
{
  Serial.begin(115200);
  while (!Serial);

  Serial.println("\nStarting ESP8266-RepeatingClient on " + String(ARDUINO_BOARD));
  Serial.println(WEBSOCKETS2_GENERIC_VERSION);
  pinMode(pin, OUTPUT);//设置输出模式
  digitalWrite(pin, var);//默认输出低电平,也就是打开状态
  // Connect to wifi
  WiFi.begin(ssid, password);//连接 wifi

  // Wait some time to connect to wifi
  for (int i = 0; i < 10 && WiFi.status() != WL_CONNECTED; i++) 
  {
    Serial.print(".");
    delay(1000);
  }

  // Check if connected to wifi
  if (WiFi.status() != WL_CONNECTED) 
  {
    Serial.println("No Wifi!");
    return;
  }

   Serial.print("Connected to Wifi, Connecting to WebSockets Server @");
   Serial.println(websockets_server_host); 
     client.addHeader("Origin", "http://"+String(websockets_server_host));//设置来源地址,保持和服务器地址一致,防止跨域被拦截,默认是当前库的 github 地址
    //client.addHeader("Authorization", "Basic YWRtaW46YWRtaW4="); //如果使用的是原始的库,并且使用的是spring security 因为会默认添加无数据的Authorization头,可能会出现 401,需要添加账号密码 ,或者修改库的底层源码去掉默认添加的 Authorization 空头,内容是Basic 账号:密码的base64,可以通过修改库的底层源码去掉默认空的认证信息
  
  // run callback when messages are received
  client.onMessage([&](WebsocketsMessage message) 
  {
    Serial.print("Got Message: ");
     String command =message.data(); //获取到服务端发来的数据
     Serial.print(command);
     Serial.print("\n");
    if(command =="0"){ //如果服务器发送的是 0 则设置状态为 0 低电平
      var =0;
     // Serial.println("0");
     digitalWrite(pin, var);//将电平状态从 gpio 地址写出去
    }
    else if(command =="1"){//如果服务器发送的是 1 则设置状态为 1 高电平
     // Serial.println("1");
      var =1;
      digitalWrite(pin, var);//将电平状态从 gpio 地址写出去
    }
    
  });

  // run callback when events are occuring
  client.onEvent(onEventsCallback); //设置websocket 的回调
}






void sendMessage(void)
{
// try to connect to Websockets server
  //连接方式 1
  bool connected = client.connect(websockets_server_host, websockets_server_port, "/websocket/1234567890"); //和服务器连接,主机和地址在 defines 文件中声明
   //连接方式 2
  //bool connected =  client.connect("ws://"+String(websockets_server_host)+":"+String(websockets_server_port)+"/websocket/1234567890"); //比如ws://192.168.3.2/websocket/aaaa

  if (connected) 
  {
    Serial.println("Connected!");
    status=1; //连接后修改状态为已连接
    String WS_msg = String("Hello to Server from ") + BOARD_NAME;
    client.send(WS_msg); //随便发送了一条消息
  } 
  else 
  {
    Serial.println("Not Connected!");
  }
}

void checkToSendMessage()
{
  #define REPEAT_INTERVAL    20000L
  
  static unsigned long checkstatus_timeout = 0;

  // Send WebSockets message every REPEAT_INTERVAL (10) seconds.
  //重连检查,每 10 秒检查一下,如果是关闭状态则重新连接
  if (((millis() > checkstatus_timeout) || (checkstatus_timeout == 0))&&status==0)
  {
    sendMessage();
    checkstatus_timeout = millis() + REPEAT_INTERVAL;
  }else if (((millis() > checkstatus_timeout) || (checkstatus_timeout == 0))&&status==1){//如果是连接状态,则每 20 秒发送一条 ping 消息
    client.send("ping");
    checkstatus_timeout = millis() + REPEAT_INTERVAL;
    }
}
//初始循环
void loop() 
{

  checkToSendMessage();
  
  // let the websockets client check for incoming messages
  if (client.available()) 
  {
    client.poll();
  }


}
